/*
 * CgDeclaration.c
 *
 *  Created on: 2012/06/07
 *      Author: guanxiaoying
 */
#include "../coredef.h"
#include "../cc/cc.h"
#include "cg.h"
static VOID cg_DeclSetCurrFunction( AST astFunc ){
	AST astMax;
	stFunctionNestAccess.alloc(1);
	astMax = stFunctionNestAccess.getMax();
	stFunctionNestAccess.function.set( astMax, astFunc );
}
static VOID cg_DeclFunctionBody( AST astFunc, AST astStmt ){
	AST astRetCmdList;
	AST astEnd;
	CG_RESULT res;

	cg_DeclSetCurrFunction(astFunc);
	astRetCmdList = CG_NewFuncEntryCmdList( astStmt );
	astEnd = CG_NewFuncExitCmdList( astStmt );
	stFunctionInfoAccess.functionExit.set( astFunc, astEnd );
	res = CG_Statement( astStmt, FALSE );
	stCmdListAccess.next.set( astRetCmdList, res.astBegin );
	stCmdListAccess.before.set( res.astBegin , astRetCmdList );
	CG_MergeCmdList( res, astEnd );
	stFunctionInfoAccess.functionEntry.set( astFunc, astRetCmdList );
}
CG_RESULT CG_Declaration( AST astDeclaration ){
	AST astDeclarator;
	AST astChildDeclarator;
	AST astSym;
	AST astInitialExp;
	AST astExp;
	AST astTypeSpecifier;
	AST astCgNew;
	AST astStmt;
	CG_RESULT result = {0,0};
	CG_RESULT result_child = {0,0};
	TRY;
	astTypeSpecifier = stDeclarationAccess.typeSpecifier.get( astDeclaration );
	if( stTypeSpecifierAccess.externNum.get( astTypeSpecifier ) > 0 ){
		CG_StaticDeclaration( astDeclaration );
		return result;
	}
	if( stTypeSpecifierAccess.staticNum.get( astTypeSpecifier ) > 0 ){
		CG_StaticDeclaration( astDeclaration );
		return result;
	}

	astDeclarator = stDeclarationAccess.declarator.get( astDeclaration );
	while( astDeclarator ){
		astSym = CcDeclGetSymfromDec( astDeclarator );
		astChildDeclarator = astDeclarator;
		astInitialExp = 0;
		while( astChildDeclarator ){
			if( stDeclaratorAccess.declaratorKind.get( astChildDeclarator ) == DECLARATOR_INIT ){
				astInitialExp = stDeclaratorAccess.initialExpList.get( astChildDeclarator );
			}else if( stDeclaratorAccess.declaratorKind.get( astChildDeclarator ) == DECLARATOR_ARRAY ){
				astExp = stDeclaratorAccess.arrayIdx.get( astChildDeclarator );
				result_child = CG_Expression( astExp, FALSE );
				result = CG_MergeResult( result, result_child );
			}
			astChildDeclarator = stDeclaratorAccess.childDeclarator.get( astChildDeclarator );
		}
		TRY;
		if( astSym > 0 ){
			if( stTypeSpecifierAccess.typedefNum.get( astTypeSpecifier ) == 0 ){
				if( stSymbolInfoAccess.kind.get( astSym ) == SYMBOL_KIND_FUNCTION ){
					astStmt = stSymbolInfoAccess.functionBody.get( astSym );
					astCgNew = CG_ConvertToFunction( astSym );
					if( astStmt != 0 ){
						cg_DeclFunctionBody( astCgNew, astStmt );
						return result;
					}
				}else if( stSymbolInfoAccess.kind.get( astSym ) == SYMBOL_KIND_VARIABLE ){
					astCgNew = CG_ConvertToTemporaryVariable( astSym );
					if( astInitialExp != 0 ){
						result_child = CG_AssignInitializerToVariable( astCgNew, astInitialExp, TRUE );
						result = CG_MergeResult( result, result_child );
					}
				}
			}
		}
		CATCH(result);
		astDeclarator = stDeclaratorAccess.nextDeclarator.get( astDeclarator );
	}
	CATCH( result );
	return result;
}

AST  CG_DeclGetCurrFunction( VOID ){
	AST astMax;
	astMax = stFunctionNestAccess.getMax();
	return stFunctionNestAccess.function.get( astMax );
}
/*
 * global declaration
 */
VOID CG_StaticDeclaration( AST astDeclaration ){
	AST astDeclarator;
	AST astSym;
	AST astLink;
	AST astCgNew;
	AST astChain;
	AST astStmt;
	AST astInitialExp;
	astDeclarator = stDeclarationAccess.declarator.get( astDeclaration );
	while( astDeclarator ){
		astSym = CcDeclGetSymfromDec( astDeclarator );
		astInitialExp = 0;
		if( stDeclaratorAccess.declaratorKind.get( astDeclarator ) == DECLARATOR_INIT ){
			astInitialExp = stDeclaratorAccess.initialExpList.get( astDeclarator );
		}
		if( astSym > 0 ){
			astLink = stSymbolInfoAccess.linkage.get( astSym );
			if( astLink != 0 ){
				astCgNew = stCCLinkageAccess.definitionSym.get( astLink );
				if( astCgNew == 0 ){
					astChain = stCCLinkageAccess.definitionChain.get( astLink );
					if( astChain == 0 ){
						astChain = stCCLinkageAccess.tenDeclChain.get( astLink );
					}
					if( astChain != 0 ){
						TRY;
						astSym = stUniteChainAccess.parameter_sym.get( astChain );
						if( stSymbolInfoAccess.kind.get( astSym ) == SYMBOL_KIND_FUNCTION ){
							astCgNew = CG_ConvertToFunction( astSym );
							astStmt = stSymbolInfoAccess.functionBody.get( astSym );
							if( astStmt != 0 ){
								cg_DeclFunctionBody( astCgNew, astStmt );
							}
						}else if( stSymbolInfoAccess.kind.get( astSym ) == SYMBOL_KIND_VARIABLE ){
							astCgNew = CG_ConvertToVariable( astSym );
							if( astInitialExp != 0 ){
								CG_AssignInitializerToVariable( astCgNew, astInitialExp, FALSE );
							}
						}
						stCCLinkageAccess.definitionSym.set( astLink, astCgNew );
						CATCH((VOID)0);
					}
				}
			}
		}
		astDeclarator = stDeclaratorAccess.nextDeclarator.get( astDeclarator );
	}
}

